import type {
  IGameState,
  ITowerState,
  TowerID,
  IPlayerState,
  PlayerID,
  CardID,
  ICardState,
  LaneID,
  CardLocation
} from './types'


import {
  BOARD_WIDTH_SIZE
} from './config'

// 数据状态记录
export class GameStateManager {
  private currentState: IGameState
  private stateHistory: IGameState[] = []
  private maxHistorySteps = 50 // 最大历史记录步数

  constructor(initialState: IGameState) {
    this.currentState = this.deepCloneState(initialState)
    this.saveHistory()
  }

  // 获取当前状态
  public getState(): IGameState {
    return this.deepCloneState(this.currentState)
  }

  // 更新游戏状态
  public updateState(updater: (state: IGameState) => IGameState): IGameState {
    const newState = updater(this.deepCloneState(this.currentState))
    this.validateStateTransition(this.currentState, newState)
    this.currentState = newState
    this.saveHistory()
    return this.getState()
  }

  // 回滚到上一个状态
  public undo(): IGameState | null {
    if (this.stateHistory.length <= 1) return null

    this.stateHistory.pop() // 移除当前状态
    this.currentState = this.stateHistory.pop()! // 获取上一个状态
    this.saveHistory() // 重新保存当前状态
    return this.getState()
  }

  // 重置到初始状态
  public resetToInitial(): IGameState {
    this.currentState = this.deepCloneState(this.stateHistory[0])
    this.stateHistory = [this.getState()]
    return this.getState()
  }

  // 保存历史记录
  private saveHistory(): void {
    this.stateHistory.push(this.deepCloneState(this.currentState))

    // 限制历史记录大小
    if (this.stateHistory.length > this.maxHistorySteps) {
      this.stateHistory.shift()
    }
  }

  // 状态验证
  private validateStateTransition(oldState: IGameState, newState: IGameState): void {
    // 这里可以添加各种验证规则
    if (oldState.gameId !== newState.gameId) {
      throw new Error('Cannot change game ID')
    }

    // 添加更多验证规则...
  }

  // 深度克隆状态
  private deepCloneState<T>(state: T): T {
    return JSON.parse(JSON.stringify(state))
  }
}

export const buildPlayerData = (id: PlayerID): IPlayerState => {
  return {
    id,
    name: 'Player One',
    health: 40,
    mana: 3,
    maxMana: 3,
    gold: 0,
    deck: [],
    hand: [],
    discardPile: [],
    items: [],
    heroes: [],
    passed: false
  }
}

export const buildTowerData = (id: TowerID): ITowerState => {
  return {
    id,
    health: 0,
    armor: 0,
    isAncient: false
  }
}

export const buildCardData = (
  instanceId: CardID,
  location: CardLocation,
  cardData: any
): ICardState => {
  let definitionId = undefined
  let name = undefined
  let imagePath = undefined
  if (cardData && typeof cardData === 'object') {
    definitionId = cardData['id']
    name = cardData['name']
    imagePath = cardData['head_path']
  }

  return {
    instanceId, // 卡牌实例ID
    definitionId, // 卡牌模板ID
    name,
    pointX: 0,
    pointY: 0,
    imagePath,
    location,
    modifications: [] // 状态修改(增益/减益)
  }
}

let cardIndexSeed = 0

export class ArtifactGameStateManager extends GameStateManager {
  // 添加卡牌信息至牌堆
  public pushPlayerCards(playerId: PlayerID, cards: any) {
    return this.updateState((state) => {
      const playerState = state.players[playerId]
      if (Array.isArray(cards)) {
        cards.forEach((card) => {
          // cardId构成，p为角色id，c为卡牌，i为独立无二的索引值
          const cardId = `p-${playerId}-c-${card.id}-i-${cardIndexSeed++}`
          playerState.deck.push(cardId)
          // 公共卡牌信息注册
          state.cards[cardId] = buildCardData(cardId, { type: 'deck', owner: playerId }, card)
        })
      }
      return state
    })
  }

  // 获取玩家手牌信息
  public getPlayerCards(playerId: PlayerID) {
    const state = this.getState()
    const playerState = state.players[playerId]
    return playerState.hand.map((cardId) => state.cards[cardId])
  }

  // 玩家抽牌
  public drawCard(playerId: PlayerID, count: number = 1): IGameState {
    return this.updateState((state) => {
      const player = state.players[playerId]

      for (let i = 0; i < count; i++) {
        if (player.deck.length === 0) {
          // 牌库为空，洗牌弃牌堆
          player.deck = [...player.discardPile]
          player.discardPile = []

          if (player.deck.length === 0) {
            break // 无牌可抽
          }
        }

        const cardId = player.deck.pop()!
        player.hand.push(cardId)

        // 更新卡牌位置
        state.cards[cardId] = Object.assign({}, state.cards[cardId], {
          location: { type: 'hand', owner: playerId },
          pointX: i * BOARD_WIDTH_SIZE,
          pointY: 0,
        })
      }

      return state
    })
  }

  // 玩家打出卡牌
  public playCard(playerId: PlayerID, cardId: CardID, lane: LaneID, position: number): IGameState {
    return this.updateState((state) => {
      // 验证
      if (state.currentPlayer !== playerId) {
        throw new Error('Not your turn')
      }

      if (state.phase !== 'action') {
        throw new Error('Can only play cards during action phase')
      }

      const card = state.cards[cardId]
      const cardLocation = card.location

      if (cardLocation.type !== 'hand' || cardLocation.owner !== playerId) {
        throw new Error('Cannot play this card')
      }

      // 更新卡牌位置
      card.location = { type: 'lane', lane, position, owner: playerId }

      // 从手牌移除
      const player = state.players[playerId]
      player.hand = player.hand.filter((id) => id !== cardId)

      // 如果是英雄卡，添加到玩家英雄列表
      if (card.definitionId.startsWith('hero_')) {
        const heroId = `hero_${playerId}_${cardId}`
        state.heroes[heroId] = {
          id: heroId,
          cardId: cardId,
          owner: playerId,
          lane: lane,
          position: position,
          health: 10, // 示例值
          armor: 0,
          attack: 5, // 示例值
          abilities: [],
          isActive: true,
          cooldown: 0
        }
        player.heroes.push(heroId)
      }

      return state
    })
  }

  // 结束当前阶段
  public endPhase(): IGameState {
    return this.updateState((state) => {
      switch (state.phase) {
        case 'draft':
          state.phase = 'deployment'
          break
        case 'deployment':
          state.phase = 'action'
          break
        case 'action':
          state.phase = 'combat'
          this.resolveCombat(state)
          break
        case 'combat':
          state.phase = 'end'
          break
        case 'end':
          this.endTurn(state)
          break
        default:
          throw new Error(`Cannot end phase ${state.phase}`)
      }

      return state
    })
  }

  // 解析战斗阶段
  private resolveCombat(state: IGameState): void {
    // 实现战斗逻辑
    // 遍历所有路，解析战斗
    ; (['top', 'mid', 'bot'] as LaneID[]).forEach((lane) => {
      this.resolveLaneCombat(state, lane)
    })
  }

  // 解析单路战斗
  private resolveLaneCombat(state: IGameState, lane: LaneID): void {
    // 获取该路的所有单位
    const units = Object.values(state.heroes).filter((h) => h.lane === lane)

    // 简单战斗逻辑示例
    units.forEach((unit) => {
      if (unit.isActive) {
        // 找到攻击目标
        const target = units.find((u) => u.owner !== unit.owner)
        if (target) {
          target.health -= unit.attack

          // 检查目标是否死亡
          if (target.health <= 0) {
            this.destroyHero(state, target.id)
          }
        }
      }
    })
  }

  // 英雄死亡处理
  private destroyHero(state: IGameState, heroId: string): void {
    const hero = state.heroes[heroId]
    const player = state.players[hero.owner]

    // 从玩家英雄列表移除
    player.heroes = player.heroes.filter((id) => id !== heroId)

    // 从英雄列表移除
    delete state.heroes[heroId]

    // 卡牌进入弃牌堆
    state.cards[hero.cardId].location = { type: 'discard', owner: hero.owner }
    player.discardPile.push(hero.cardId)
  }

  // 结束回合
  private endTurn(state: IGameState): void {
    // 切换玩家
    state.currentPlayer = state.currentPlayer === 'player1' ? 'player2' : 'player1'
    state.turn++
    state.phase = 'deployment'

    // 重置玩家状态
    Object.values(state.players).forEach((player) => {
      player.passed = false
      player.maxMana = Math.min(player.maxMana + 1, 10) // 增加最大法力
      player.mana = player.maxMana // 恢复法力

      // 抽牌
      this.drawCard(player.id, 1)
    })
  }
}
